/******************************************************************************
*		Output a pulse everytime pressing the key.
*******************************************************************************/

module keyPulse #(
  parameter   SYS_CLK = 50_000_000
)(
  input       clk ,
  input       rstn,
  input       ikey,

  output reg  okey
);

localparam CNT_MAX = SYS_CLK / 50;

/*    debug   */
// localparam CNT_MAX = 50;

reg  [25:0]     cnt_20ms ;

/*          detect edge         */
reg  key_in_r;
wire key_pos, key_neg;

always @(posedge clk or negedge rstn) begin
  if (~rstn) begin
    key_in_r    <=  1'b1;
  end else begin
    key_in_r    <=  ikey;
  end
end

assign key_pos = (ikey && ~key_in_r) ? 1'b1 : 1'b0;
assign key_neg = (~ikey && key_in_r) ? 1'b1 : 1'b0;

/*          FSM         */
reg  [2:0]  nstate, cstate;
localparam  IDLE    = 3'b001,
            SAMPLE  = 3'b010,
						CONFIRM = 3'b100;

always @(posedge clk or negedge rstn) begin
  if (~rstn)
    cstate  <=  IDLE;
  else 
    cstate  <=  nstate;
end

always @(*) begin
  nstate = cstate;
  case (cstate)
    IDLE:
      if (key_neg)
				nstate = SAMPLE;
    SAMPLE: 
			begin
      	if (key_pos)    
        	nstate = IDLE;
				else if (cnt_20ms == CNT_MAX - 1)
					nstate = CONFIRM;
			end
		CONFIRM:
			nstate = IDLE;
    default: nstate = cstate;
  endcase
end

always @(posedge clk or negedge rstn) begin
  if(~rstn)
    okey  <=  1'b0;
  else begin
    case (nstate)
      IDLE: 
     	  okey   <= 1'b0;
      SAMPLE: 
     	  okey   <= 1'b0;
	  	CONFIRM:
	  		okey 	 <= 1'b1;
      default:
	  		okey	 <= okey;
    endcase
  end
end

/*          cnt_20ms            */
always @(posedge clk or negedge rstn) begin
  if (~rstn) 
    cnt_20ms    <=  26'd0;
  else if (nstate == SAMPLE) 
    cnt_20ms    <=  cnt_20ms + 1'b1;
  else
    cnt_20ms    <=  26'd0;
end

endmodule
